{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4.2 Universal Functions: Fast Element-Wise Array Functions（通用函数：快速点对点数组函数）\n",
    "\n",
    "universal function, 或 ufunc, 是用来在ndarray中实现element-wise操作的。\n",
    "\n",
    "可以认为这个ufunc可以把一些简单的函数做快速的向量化封装，输入是一个以上的标量，输出也是一个以上的标量。\n",
    "\n",
    "很多ufuncs都是点对点的变换，像sqrt或exp："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "arr = np.arange(10)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.        ,  1.        ,  1.41421356,  1.73205081,  2.        ,\n",
       "        2.23606798,  2.44948974,  2.64575131,  2.82842712,  3.        ])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  1.00000000e+00,   2.71828183e+00,   7.38905610e+00,\n",
       "         2.00855369e+01,   5.45981500e+01,   1.48413159e+02,\n",
       "         4.03428793e+02,   1.09663316e+03,   2.98095799e+03,\n",
       "         8.10308393e+03])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.exp(arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这些函数叫做一元通用函数（unary ufuncs）。其他一些函数，比如add或maximum，需要两个数组（binary ufuncs）,并返回一个数组作为结果："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.18373557, -1.82728347, -0.11149882, -1.34286776, -1.09016986,\n",
       "        1.63308   ,  1.05205535, -0.32746706])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.random.randn(8)\n",
    "y = np.random.randn(8)\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-0.42410809,  1.89603273, -1.13649816, -0.98559379, -0.16827718,\n",
       "        0.52828569,  1.57543351,  1.50045399])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.18373557,  1.89603273, -0.11149882, -0.98559379, -0.16827718,\n",
       "        1.63308   ,  1.57543351,  1.50045399])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.maximum(x, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里mamimum点对点的比较x和y中的元素。\n",
    "\n",
    "尽管不常见，但ufunc也能返回多个数组。例如modf，这是一个向量版的divmod（python内建函数），modf会返回小数部分和整数部分：\n",
    "\n",
    ">本函数是实现a除以b，然后返回商与余数的元组。如果两个参数a,b都是整数，那么会采用整数除法，结果相当于（a//b, a % b)。如果a或b是浮点数，相当于（math.floor(a/b), a%b)。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.51538382, -0.75054846,  0.02863286,  8.74026861, -3.44529124,\n",
       "       -9.18401768, -0.68469611])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(7) * 5\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.51538382, -0.75054846,  0.02863286,  0.74026861, -0.44529124,\n",
       "       -0.18401768, -0.68469611])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "remainder, whole_part = np.modf(arr)\n",
    "remainder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1., -0.,  0.,  8., -3., -9., -0.])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "whole_part"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "ufunc能接受一个可选参数作为输出，这样可以直接更改原有的数组："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.51538382, -0.75054846,  0.02863286,  8.74026861, -3.44529124,\n",
       "       -9.18401768, -0.68469611])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/xu/anaconda/envs/py35/lib/python3.5/site-packages/ipykernel/__main__.py:1: RuntimeWarning: invalid value encountered in sqrt\n",
      "  if __name__ == '__main__':\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([ 1.23100927,         nan,  0.16921248,  2.95639453,         nan,\n",
       "               nan,         nan])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(arr) # 没有改变原有的arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/xu/anaconda/envs/py35/lib/python3.5/site-packages/ipykernel/__main__.py:1: RuntimeWarning: invalid value encountered in sqrt\n",
      "  if __name__ == '__main__':\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([ 1.23100927,         nan,  0.16921248,  2.95639453,         nan,\n",
       "               nan,         nan])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(arr, arr) # 改变了原有的arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.23100927,         nan,  0.16921248,  2.95639453,         nan,\n",
       "               nan,         nan])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "一些一元通用函数：\n",
    "\n",
    "![](../MarkdownPhotos/chp04/屏幕快照 2017-10-25 下午1.19.41.png)\n",
    "\n",
    "\n",
    "\n",
    "一些二元通用函数：\n",
    "![](../MarkdownPhotos/chp04/屏幕快照 2017-10-25 下午1.21.08.png)\n",
    "\n",
    "![](../MarkdownPhotos/chp04/屏幕快照 2017-10-25 下午1.21.42.png)\n",
    "\n"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [py35]",
   "language": "python",
   "name": "Python [py35]"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
